package main

/*
#cgo CFLAGS: -I./
#cgo LDFLAGS:-Wl,-rpath,./
#cgo LDFLAGS: -L./ -ltest
#include "test.h"
int testCB(struct info *);
extern void cgoCall(void *, int); // 这里与api.h中的IntCallback保持类型一致
*/
import "C"
import (
	"fmt"
	"time"
	"unsafe"
)

var tmp = make([]byte, 4)

func main() {
	C.setcallback(C.cb(C.testCB))
	// C.call()
	C.Init()
	// C.clean()
	fmt.Println(string(tmp))

	/************************************************/
	one := OneCaller{}
	SecSetCallback(one)
	DoCallback(1234)
	another := AnotherCaller{}

	SecSetCallback(another)

	ch := make(chan bool)

	go func(ch chan bool) {
		for {
			select {
			case chv := <-ch:
				fmt.Println(chv)
				return
			default:
				DoCallback(5678)
				time.Sleep(time.Second * 2)
			}
		}
	}(ch)

	time.Sleep(time.Second * 10)
	chv := <-ch
	fmt.Println(chv)
}

//export testCB
func testCB(info *C.struct_info) C.int {
	tmp = C.GoBytes(unsafe.Pointer(info.a), info.size)
	fmt.Println("===", string(tmp))
	return 1
}

/*************************************************************/

type Caller interface {
	Call(int)
}

type OneCaller struct{}
type AnotherCaller struct{}

func (o OneCaller) Call(value int) {
	fmt.Println("one:", value)
}

func (o AnotherCaller) Call(value int) {
	fmt.Println("another:", value)
}

//export cgoCall
func cgoCall(p unsafe.Pointer, number C.int) {
	caller := *(*Caller)(p)
	caller.Call(int(number))
}

func SecSetCallback(caller Caller) {
	C.SetIntCallback(C.IntCallback(C.cgoCall), unsafe.Pointer(&caller))
}

func DoCallback(value int) {
	C.DoIntCallback(C.int(value))
}
